
class WeCan {

  version = '1.0.0'; // 版本号
  author = '喵一下'; // 作者
  description = '一个支持链式调用 在内存中渲染的canvas'; // 描述

  canvas = null;
  ctx = null;
  width = 0;
  height = 0;
  #taskQueue = [];


  /**
   * 构造函数
   * @param {object} options
   * @param {number} options.width
   * @param {number} options.height
   */
  constructor(options = {}) {
    this.width = options.width || 300;
    this.height = options.height || 300;
    this.#init();
  }

  // 初始化
  #init() {
    try {
      this.canvas = document.createElement('canvas');
      this.canvas.width = this.width;
      this.canvas.height = this.height;
      this.ctx = this.canvas.getContext('2d');
      return this;
    } catch (e) {
      console.error(e);
    }
  }


  /**
   * 添加背景
   * @param {string} url 
   * @returns {this} 返回当前实例对象，可以链式调用
   */
  addBackground(url) {
    this.#taskQueue.push(() => {
      return this.#renderBackground(url);
    });
    return this;
  }

  // 渲染背景
  async #renderBackground(url) {
    const img = new Image();
    img.src = url;
    img.crossOrigin = 'anonymous';
    img.width = this.width;
    img.height = this.height;
    await new Promise((resolve) => {
      img.onload = () => {
        this.ctx.drawImage(img, 0, 0, this.width, this.height);
        resolve(this);
      }
      img.onerror = (e) => {
        console.error('图片加载失败', e);
        resolve(this);
      }
    });
    return this;
  }



  /**
   * 添加文字
   * @param {string} text 
   * @param {object} options
   * @param {number} options.x
   * @param {number} options.y
   * @param {string} options.color
   * @param {number} options.fontSize
   * @param {string} options.fontFamily
   * @param {string} options.textAlign
   * @param {string} options.textBaseline
   * @param {string} options.fontWeight
   * @returns {this} 返回当前实例对象，可以链式调用
   */
  addText(text, options = {}) {
    this.#taskQueue.push(() => {
      return this.#renderText(text, options);
    });
    return this;
  }

  // 渲染文字
  #renderText(text, options = {}) {
    let { x = 0, y = 0, color = '#000', fontSize = 16, fontFamily = 'PingFang SC', textAlign = 'start', textBaseline = 'top', fontWeight = 'normal' } = options;
    this.ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
    this.ctx.fillStyle = color;
    this.ctx.textBaseline = textBaseline;
    if (textAlign === 'center') {
      const textWidth = this.ctx.measureText(text).width;
      x = (this.width - textWidth) / 2;
    }
    this.ctx.fillText(text, x, y);
    return this;
  }



  /**
   * 添加图片
   * @param {string} url 图片地址或者base64
   * @param {object} options 
   * @param {number} options.x
   * @param {number} options.y
   * @param {number} options.width
   * @param {number} options.height
   * @returns {this} 返回当前实例对象，可以链式调用
   */
  addImage(url, options = {}) {
    this.#taskQueue.push(() => {
      return this.#renderImage(url, options);
    });
    return this;
  }

  // 渲染图片
  async #renderImage(url, options = {}) {
    const { x = 0, y = 0, width = 0, height = 0 } = options;
    const img = new Image();
    img.src = url;
    img.crossOrigin = 'anonymous';
    img.width = width;
    img.height = height;
    await new Promise((resolve) => {
      img.onload = () => {
        this.ctx.drawImage(img, x, y, width, height);
        resolve(this);
      }
      img.onerror = (e) => {
        console.error('图片加载失败', e);
        resolve(this);
      }
    });
    return this;
  }


  // 执行任务
  async #run() {
    while (this.#taskQueue.length > 0) {
      const task = this.#taskQueue.shift();
      await task();
    }
    return this;
  }

  /**
   * 返回渲染后的结果-base64
   * @returns {Promise<string>} 
   */
  async dataURL() {
    await this.#run();
    return this.canvas.toDataURL();
  }

  /**
   * 清除画布
   * @returns {this}
   */
  clear() {
    this.ctx.clearRect(0, 0, this.width, this.height);
    return this;
  }

  /**
   * 销毁
   * @returns {boolean}
   */
  destroy() {
    this.canvas = null;
    this.ctx = null;
    this.width = 0;
    this.height = 0;
    this.#taskQueue = [];
    return true;
  }

}

export default WeCan;